﻿using UnityEngine;
using System.Collections;
using System;
using System.IO;

namespace MyAssetBundles {
    public abstract class MyAssetBaseOperation : CustomYieldInstruction {
        public string error = null;
        public AsyncOperation operation = null;
        public abstract IEnumerator RaiseEvent ();
        public abstract void Destroy ();
        public bool isDone
        {
            get {
                return (operation != null && operation.isDone) || error != null;
            }
        }

        public override bool keepWaiting
        {
            get {
                return !isDone;
            }
        }
    }
    
    public delegate void MyAssetHandler (UnityEngine.Object asset);
    public class MyAssetOperation : MyAssetBaseOperation {
        public string assetBundleName;
        public string assetName;
        public Type assetType = typeof(UnityEngine.GameObject);
        public event MyAssetHandler onEventMyAsset;
        public override IEnumerator RaiseEvent ()
        {
            yield return this;
            if (onEventMyAsset != null)
            {
                AssetBundleRequest request = operation as AssetBundleRequest;
                UnityEngine.Object asset = request != null ? request.asset : null;
                onEventMyAsset(asset);
                onEventMyAsset = null;
            }
        }

        public override void Destroy () { }

        public static string GetKey (string assetBundleName, string assetName, Type assetType)
        {
            return string.Format("{0}/{1}/{2}", assetBundleName, assetName, assetType.ToString());
        }
    }

    public class MyDependenciesOperation : MyAssetBaseOperation {
        public string assetBundleName;
        protected int reference = 1;
        public void Retain () { reference++; }
        public void Release () { reference--; }
        public bool isUnused
        { 
            get {
                if (!isDone) return false;
                return !(reference > 0);
            }
        }

        public override IEnumerator RaiseEvent ()
        {
            yield return this;
            if (error != null) yield break;
            AssetBundleCreateRequest request = operation as AssetBundleCreateRequest;
            if (request == null || request.assetBundle == null)
            {
                error = "without asset bundle";
                this.operation = null;
            }
        }
        public override void Destroy ()
        {
            AssetBundleCreateRequest request = operation as AssetBundleCreateRequest;
            if (request != null && request.assetBundle != null)
            {
                request.assetBundle.Unload(false);
            }
        }
    }

    public delegate IEnumerator MyAssetBundleHandler (string assetBundleName, AssetBundle assetBundle);
    public class MyAssetBundleOperation : MyDependenciesOperation {
        public event MyAssetBundleHandler onEventMyAssetBundle;
        public override IEnumerator RaiseEvent ()
        {
            yield return base.RaiseEvent();
            
            if (onEventMyAssetBundle != null)
            {
                AssetBundleCreateRequest request = operation as AssetBundleCreateRequest;
                AssetBundle assetBundle = request != null ? request.assetBundle : null;
                yield return onEventMyAssetBundle(assetBundleName, assetBundle);
            }
            onEventMyAssetBundle = null;
            reference = 0;
        }
    }
}

